home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / boot / scsiDiskBoot / fsDisk.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-06-15  |  15.7 KB  |  483 lines

  1. /* 
  2.  * fsDisk.c --
  3.  *
  4.  *    Routines related to managing local disks.  Each partition of a local
  5.  *    disk (partitions are defined by a table on the disk header) is
  6.  *    called a ``domain''.  FsAttachDisk attaches a domain into the file
  7.  *    system, and FsDeattachDisk removes it.  A domain is given
  8.  *    a number the first time it is ever attached.  This is recorded on
  9.  *    the disk so it doesn't change between boots.  The domain number is
  10.  *    used to identify disks, and a domain number plus a file number is
  11.  *    used to identify files.  FsDomainFetch is used to get the state
  12.  *    associated with a disk, and FsDomainRelease releases the reference
  13.  *    on the state.  FsDetachDisk checks the references on domains in
  14.  *    the normal (non-forced) case so that active disks aren't detached.
  15.  *
  16.  * Copyright 1987 Regents of the University of California
  17.  * All rights reserved.
  18.  * Permission to use, copy, modify, and distribute this
  19.  * software and its documentation for any purpose and without
  20.  * fee is hereby granted, provided that the above copyright
  21.  * notice appear in all copies.  The University of California
  22.  * makes no representations about the suitability of this
  23.  * software for any purpose.  It is provided "as is" without
  24.  * express or implied warranty.
  25.  */
  26.  
  27. #ifdef notdef
  28. static char rcsid[] = "$Header: /sprite/src/kernel/fs/RCS/fsDisk.c,v 8.7 89/06/02 12:57:50 jhh Exp Locker: jhh $ SPRITE (Berkeley)";
  29. #endif not lint
  30.  
  31.  
  32. #include "sprite.h"
  33.  
  34. #include "fsBoot.h"
  35. #include "devDiskLabel.h"
  36. #include "dev.h"
  37. #include "sync.h"
  38. #include "machMon.h"
  39. /*
  40.  * fsDevice is copied into all FsLocalFileIOHandles.  It is used by the drivers
  41.  * to get to the partition and geometry information for the disk.
  42.  */
  43. Fs_Device fsDevice;
  44.  
  45. /*
  46.  * fsDomainPtr and fsRootHandlePtr are used by Fs_Open.
  47.  */
  48. static FsDomain fsDomain;
  49. FsDomain *fsDomainPtr = &fsDomain;
  50. static FsLocalFileIOHandle fsRootHandle;
  51. FsLocalFileIOHandle *fsRootHandlePtr = &fsRootHandle;
  52.  
  53. /*
  54.  * Forward declarations.
  55.  */
  56. static int    InstallLocalDomain();
  57. void        AddDomainFlags();
  58. static Boolean    IsSunLabel();
  59. static Boolean    IsSpriteLabel();
  60.  
  61. /*
  62.  *----------------------------------------------------------------------
  63.  *
  64.  * FsAttachDisk --
  65.  *
  66.  *    Make a particular local disk partition correspond to a prefix.
  67.  *    This makes sure the disk is up, reads the domain header,
  68.  *    and calls the initialization routine for the block I/O module
  69.  *    of the disk's driver.  By the time this is called the device
  70.  *    initialization routines have already been called from Dev_Config
  71.  *    so the device driver knows how the disk is partitioned into
  72.  *    domains.  This routine sees if the domain is formatted correctly,
  73.  *    and if so attaches it to the set of domains.
  74.  *
  75.  * Results:
  76.  *    SUCCESS if the disk was readable and had a good domain header.
  77.  *
  78.  * Side effects:
  79.  *    Sets up the FsDomainInfo for the domain.
  80.  *
  81.  *----------------------------------------------------------------------
  82.  */
  83. ReturnStatus
  84. FsAttachDisk(ctlrNum, unitNum, partNum)
  85.     int ctlrNum;    /* Controller number from boot command */
  86.     int unitNum;    /* Unit number from boot command */
  87.     int partNum;    /* Partition number from boot command */
  88. {
  89.     ReturnStatus status;        /* Error code */
  90.     register Address buffer;        /* Read buffer */
  91.     int headerSector;            /* Starting sector of domain header */
  92.     int numHeaderSectors;        /* Number of sectors in domain header */
  93.     int summarySector;            /* Sector of summary information. */
  94.     FsSummaryInfo *summaryInfoPtr;    /* Pointer to summary info. */
  95.     int amountRead;            /* Returned from read call */
  96.  
  97.     /*
  98.      * Set up the global filesystem device, its type number is zero.
  99.      */
  100.     fsDevice.unit = unitNum;
  101. #ifdef SCSI_DISK_BOOT
  102.     fsDevice.type = 0;
  103. #endif
  104. #ifdef XYLOGICS_BOOT
  105.     fsDevice.type = FS_DEV_XYLOGICS;
  106. #endif
  107.     /*
  108.      * Open the raw disk device so we can grub around in the header info.
  109.      */
  110.     status = (*devFsOpTable[DEV_TYPE_INDEX(fsDevice.type)].open)(&fsDevice);
  111.     if (status != SUCCESS) {
  112.     return(status);
  113.     }
  114.     buffer = (Address)malloc(DEV_BYTES_PER_SECTOR);
  115.  
  116.     /*
  117.      * Read the zero'th sector of the partition.  It has a copy of the
  118.      * zero'th sector of the whole disk which describes how the rest of the
  119.      * domain's zero'th cylinder is layed out.
  120.      */
  121.     status = (*devFsOpTable[DEV_TYPE_INDEX(fsDevice.type)].read)(&fsDevice,
  122.         0, DEV_BYTES_PER_SECTOR, buffer, &amountRead);
  123.     if (status != SUCCESS) {
  124.     return(status);
  125.     }
  126.     /*
  127.      * Check for different disk formats, and figure out how the rest
  128.      * of the zero'th cylinder is layed out.
  129.      */
  130.     if (((Sun_DiskLabel *)buffer)->magic != SUN_DISK_MAGIC) {
  131.     /*
  132.      * For Sun formatted disks we put the domain header well past
  133.      * the disk label and the boot program.
  134.      */
  135.     }
  136.  
  137.     headerSector = SUN_DOMAIN_SECTOR;
  138.     numHeaderSectors = FS_NUM_DOMAIN_SECTORS;
  139.     /*
  140.      * Read the domain header and save it with the domain state.
  141.      */
  142.     buffer = (Address)malloc(DEV_BYTES_PER_SECTOR * numHeaderSectors);
  143.     status = (*devFsOpTable[DEV_TYPE_INDEX(fsDevice.type)].read)(&fsDevice,
  144.         headerSector * DEV_BYTES_PER_SECTOR,
  145.         numHeaderSectors * DEV_BYTES_PER_SECTOR,
  146.         buffer, &amountRead);
  147.     if (status != SUCCESS) {
  148.     return(status);
  149.     } else if (((FsDomainHeader *)buffer)->magic != FS_DOMAIN_MAGIC) {
  150. #ifndef NO_PRINTF
  151.     printf("Bad magic <%x>\n", ((FsDomainHeader *)buffer)->magic);
  152. #endif
  153.     return(FAILURE);
  154.     }
  155.  
  156.     fsDomainPtr->headerPtr = (FsDomainHeader *) buffer;
  157.  
  158.      /*
  159.      * Set up the ClientData part of *devicePtr to reference the
  160.      * FsGeometry part of the domain header.  This is used by the
  161.      * block I/O routines.
  162.      */
  163.     ((DevBlockDeviceHandle *) (fsDevice.data))->clientData = 
  164.             (ClientData)&fsDomainPtr->headerPtr->geometry;
  165.  
  166.     /*
  167.      * Set up a file handle for the root directory.  What is important
  168.      * is the device info (for Block IO) and the file descriptor itself.
  169.      */
  170.     FsInitFileHandle(fsDomainPtr, FS_ROOT_FILE_NUMBER, fsRootHandlePtr);
  171.     return(SUCCESS);
  172. }
  173.  
  174.  
  175. /*
  176.  *----------------------------------------------------------------------
  177.  *
  178.  * IsSunLabel --
  179.  *
  180.  *    Poke around in the input buffer and see if it looks like
  181.  *    a Sun format disk label.
  182.  *
  183.  * Results:
  184.  *    TRUE or FALSE
  185.  *
  186.  * Side effects:
  187.  *    None.
  188.  *
  189.  *----------------------------------------------------------------------
  190.  */
  191. #ifdef notdef
  192. static Boolean
  193. IsSunLabel(buffer)
  194.     Address buffer;    /* Buffer containing zero'th sector */
  195. {
  196.     register Sun_DiskLabel *sunLabelPtr;
  197.  
  198.     sunLabelPtr = (Sun_DiskLabel *)buffer;
  199.     if (sunLabelPtr->magic == SUN_DISK_MAGIC) {
  200.     /*
  201.      * Should check checkSum...
  202.      */
  203.     return(TRUE);
  204.     } else {
  205.     return(FALSE);
  206.     }
  207. }
  208. #endif
  209.  
  210. /*
  211.  *----------------------------------------------------------------------
  212.  *
  213.  * IsSpriteLabel --
  214.  *
  215.  *    Poke around in the input buffer and see if it looks like
  216.  *    a Sprite format disk header.
  217.  *
  218.  * Results:
  219.  *    TRUE or FALSE
  220.  *
  221.  * Side effects:
  222.  *    None.
  223.  *
  224.  *----------------------------------------------------------------------
  225.  */
  226. #ifdef notdef
  227. static Boolean
  228. IsSpriteLabel(buffer)
  229.     Address buffer;    /* Buffer containing zero'th sector */
  230. {
  231.     register FsDiskHeader *diskHeaderPtr;
  232.     register int index;
  233.     register int checkSum;
  234.  
  235.     diskHeaderPtr = (FsDiskHeader *)buffer;
  236.     if (diskHeaderPtr->magic == FS_DISK_MAGIC) {
  237.         return(TRUE);
  238.     }
  239.     }
  240.     return(FALSE);
  241. }
  242. #endif
  243.  
  244. /*
  245.  *----------------------------------------------------------------------
  246.  * The following routines are used by device drivers to map from block
  247.  * and sector numbers to disk addresses.  There are two sets, one for
  248.  * drivers that use logical sector numbers (i.e. SCSI) and the other
  249.  * for <cyl,head,sector> format disk addresses.
  250.  *----------------------------------------------------------------------
  251.  */
  252.  
  253. /*
  254.  *----------------------------------------------------------------------
  255.  *
  256.  * Fs_BlocksToSectors --
  257.  *
  258.  *    Convert from block indexes (actually, fragment indexes) to
  259.  *    sectors using the geometry information on the disk.  This
  260.  *    is a utility for block device drivers.
  261.  *
  262.  * Results:
  263.  *    The sector number that corresponds to the fragment index.
  264.  *    The caller has to make sure that its I/O doesn't cross a
  265.  *    filesystem block boundary.
  266.  *
  267.  * Side effects:
  268.  *    None.
  269.  *
  270.  *----------------------------------------------------------------------
  271.  */
  272. #define SECTORS_PER_FRAG    (FS_FRAGMENT_SIZE / DEV_BYTES_PER_SECTOR)
  273. #ifdef SCSI_DISK_BOOT
  274. int
  275. Fs_BlocksToSectors(fragNumber, data)
  276.     int fragNumber;    /* Fragment index to map into block index */
  277.     ClientData data;    /* ClientData from the device info */
  278. {
  279.     register FsGeometry *geoPtr;
  280.     register int sectorNumber;    /* The sector corresponding to the fragment */
  281.     register int cylinder;    /* The cylinder number of the fragment */
  282.     register int rotationalSet;    /* The rotational set with cylinder of frag */
  283.     register int blockNumber;    /* The block number within rotational set */
  284.  
  285.     geoPtr         = (FsGeometry *)data;
  286.     blockNumber        = fragNumber / FS_FRAGMENTS_PER_BLOCK;
  287.     cylinder        = blockNumber / geoPtr->blocksPerCylinder;
  288.     blockNumber        -= cylinder * geoPtr->blocksPerCylinder;
  289.     rotationalSet    = blockNumber / geoPtr->blocksPerRotSet;
  290.     blockNumber        -= rotationalSet * geoPtr->blocksPerRotSet;
  291.  
  292.     sectorNumber = geoPtr->sectorsPerTrack * geoPtr->numHeads * cylinder +
  293.           geoPtr->sectorsPerTrack * geoPtr->tracksPerRotSet *
  294.           rotationalSet +
  295.           geoPtr->blockOffset[blockNumber];
  296.     sectorNumber += (fragNumber % FS_FRAGMENTS_PER_BLOCK) * SECTORS_PER_FRAG;
  297.  
  298.     return(sectorNumber);
  299. }
  300. #endif
  301.  
  302. /*
  303.  *----------------------------------------------------------------------
  304.  *
  305.  * Fs_BlocksToDiskAddr --
  306.  *
  307.  *    Convert from block indexes (actually, fragment indexes) to
  308.  *    disk address (head, cylinder, sector) using the geometry information
  309.  *     on the disk.  This is a utility for block device drivers.
  310.  *
  311.  * Results:
  312.  *    The disk address that corresponds to the disk address.
  313.  *    The caller has to make sure that its I/O doesn't cross a
  314.  *    filesystem block boundary.
  315.  *
  316.  * Side effects:
  317.  *    None.
  318.  *
  319.  *----------------------------------------------------------------------
  320.  */
  321. #ifdef XYLOGICS_BOOT
  322. void
  323. Fs_BlocksToDiskAddr(fragNumber, data, diskAddrPtr)
  324.     int fragNumber;    /* Fragment index to map into block index */
  325.     ClientData data;    /* ClientData from the device info */
  326.     Dev_DiskAddr *diskAddrPtr;
  327. {
  328.     register FsGeometry *geoPtr;
  329.     register int sectorNumber;    /* The sector corresponding to the fragment */
  330.     register int cylinder;    /* The cylinder number of the fragment */
  331.     register int rotationalSet;    /* The rotational set with cylinder of frag */
  332.     register int blockNumber;    /* The block number within rotational set */
  333.  
  334.     geoPtr         = (FsGeometry *)data;
  335.     /*
  336.      * Map to block number because the rotational sets are laid out
  337.      * relative to blocks.  After that the cylinder is easy because we know
  338.      * blocksPerCylinder.  To get the head and sector we first get the
  339.      * rotational set (described in fsDisk.h) of the block and the
  340.      * block's sector offset (relative to the rotational set!).  This complex
  341.      * algorithm crops up because there isn't necessarily an even number
  342.      * of blocks per track.  The 'blockOffset' array in the geometry gives
  343.      * a sector index of each successive block in a rotational set. Finally,
  344.      * we can use the sectorsPerTrack to get the head and sector.
  345.      */
  346.     blockNumber        = fragNumber / FS_FRAGMENTS_PER_BLOCK;
  347.     cylinder        = blockNumber / geoPtr->blocksPerCylinder;
  348.     blockNumber        -= cylinder * geoPtr->blocksPerCylinder;
  349.     diskAddrPtr->cylinder = cylinder;
  350.  
  351.     rotationalSet    = blockNumber / geoPtr->blocksPerRotSet;
  352.     blockNumber        -= rotationalSet * geoPtr->blocksPerRotSet;
  353. /*
  354.  * The follow statment had to be broken into two because the compiler used
  355.  * register d2 to do the modulo operation, but wasn't saving its value.
  356.  */
  357.     sectorNumber    = geoPtr->sectorsPerTrack * geoPtr->tracksPerRotSet *
  358.               rotationalSet + geoPtr->blockOffset[blockNumber];
  359.     sectorNumber    +=
  360.             (fragNumber % FS_FRAGMENTS_PER_BLOCK) * SECTORS_PER_FRAG;
  361.  
  362.     diskAddrPtr->head    = sectorNumber / geoPtr->sectorsPerTrack;
  363.     diskAddrPtr->sector = sectorNumber -
  364.               diskAddrPtr->head * geoPtr->sectorsPerTrack;
  365. }
  366. #endif
  367.  
  368. /*
  369.  *----------------------------------------------------------------------
  370.  *
  371.  * Fs_SectorsToRawDiskAddr --
  372.  *
  373.  *      Convert from a sector offset to a raw disk address (cyl, head,
  374.  *      sector) using the geometry information on the disk.  This is a
  375.  *      utility for raw device drivers and does not pay attention to the
  376.  *      rotational position of filesystem disk blocks.
  377.  *
  378.  *    This should be moved to Dev
  379.  *
  380.  * Results:
  381.  *    The disk address that corresponds exactly to the byte offset.
  382.  *
  383.  * Side effects:
  384.  *    None.
  385.  *
  386.  *----------------------------------------------------------------------
  387.  */
  388. #ifdef XYLOGICS_BOOT
  389. int
  390. Fs_SectorsToRawDiskAddr(sector, numSectors, numHeads, diskAddrPtr)
  391.     int sector;        /* Sector number (counting from zero 'til the total
  392.              * number of sectors in the disk) */
  393.     int numSectors;    /* Number of sectors per track */
  394.     int numHeads;    /* Number of heads on the disk */
  395.     Dev_DiskAddr *diskAddrPtr;
  396. {
  397.     register int sectorsPerCyl;    /* The rotational set with cylinder of frag */
  398.  
  399.     sectorsPerCyl        = numSectors * numHeads;
  400.     diskAddrPtr->cylinder    = sector / sectorsPerCyl;
  401.     sector            -= diskAddrPtr->cylinder * sectorsPerCyl;
  402.     diskAddrPtr->head        = sector / numSectors;
  403.     diskAddrPtr->sector        = sector - numSectors * diskAddrPtr->head;
  404. }
  405. #endif
  406.  
  407.  
  408. /*
  409.  *----------------------------------------------------------------------
  410.  *
  411.  * FsDeviceBlockIO --
  412.  *
  413.  *    Map a file system block address to a block device block address 
  414.  *    perform the requested operation.
  415.  *
  416.  * NOTE: This routine is temporary and should be replaced when the file system
  417.  *     is converted to use the async block io interface.
  418.  *
  419.  * Results:
  420.  *    The return status of the operation.
  421.  *
  422.  * Side effects:
  423.  *    Blocks may be written or read.
  424.  *
  425.  *----------------------------------------------------------------------
  426.  */
  427.  
  428. ReturnStatus
  429. FsDeviceBlockIO(readWriteFlag, devicePtr, fragNumber, numFrags, buffer)
  430.     int readWriteFlag;        /* FS_READ or FS_WRITE */
  431.     Fs_Device *devicePtr;    /* Specifies device type to do I/O with */
  432.     int fragNumber;        /* CAREFUL, fragment index, not block index.
  433.                  * This is relative to start of device. */
  434.     int numFrags;        /* CAREFUL, number of fragments, not blocks */
  435.     Address buffer;        /* I/O buffer */
  436. {
  437.     ReturnStatus status;    /* General return code */
  438.     int firstSector;        /* Starting sector of transfer */
  439.     DevBlockDeviceRequest    request;
  440.     DevBlockDeviceHandle    *handlePtr;
  441.     int                transferCount;
  442.  
  443.     handlePtr = (DevBlockDeviceHandle *) (devicePtr->data);
  444.     if ((fragNumber % FS_FRAGMENTS_PER_BLOCK) != 0) {
  445.     /*
  446.      * The I/O doesn't start on a block boundary.  Transfer the
  447.      * first few extra fragments to get things going on a block boundary.
  448.      */
  449.     register int extraFrags;
  450.  
  451.     extraFrags = FS_FRAGMENTS_PER_BLOCK -
  452.             (fragNumber % FS_FRAGMENTS_PER_BLOCK);
  453.     if (extraFrags > numFrags) {
  454.         extraFrags = numFrags;
  455.     }
  456.     firstSector = Fs_BlocksToSectors(fragNumber, handlePtr->clientData);
  457.     request.operation = readWriteFlag;
  458.     request.startAddress = firstSector * DEV_BYTES_PER_SECTOR;
  459.     request.startAddrHigh = 0;
  460.     request.bufferLen = extraFrags * FS_FRAGMENT_SIZE;
  461.     request.buffer = buffer;
  462.     status = Dev_BlockDeviceIOSync(handlePtr, &request, &transferCount);
  463.     extraFrags = transferCount / FS_FRAGMENT_SIZE;
  464.     fragNumber += extraFrags;
  465.     buffer += transferCount;
  466.     numFrags -= extraFrags;
  467.     }
  468.     if (numFrags > 0) {
  469.     /*
  470.      * Transfer the left over fragments.
  471.      */
  472.     firstSector = Fs_BlocksToSectors(fragNumber, handlePtr->clientData);
  473.     request.operation = readWriteFlag;
  474.     request.startAddress = firstSector * DEV_BYTES_PER_SECTOR;
  475.     request.startAddrHigh = 0;
  476.     request.bufferLen = numFrags * FS_FRAGMENT_SIZE;
  477.     request.buffer = buffer;
  478.     status = Dev_BlockDeviceIOSync(handlePtr, &request, &transferCount);
  479.     }
  480.     return(status);
  481. }
  482.  
  483.